特定の被共有中 Transit Gateway への VPC アタッチメント作成を SCP で禁止してみた
いわさです。
AWS Transit Gateway は RAM (AWS Resource Access Manager)経由で組織や外部 AWS アカウントを共有することが出来ます。
この時、特定 OU 内からこの Transit Gateway の利用を禁止したい場合に SCP で制限出来るのかを確認してみましたのでその様子を紹介します。
やりたいこと
今回やりたいことですが、Organizations 内のあるアカウントで Transit Gateway を管理しているとして、それを RAM 経由で組織に共有した際に特定の OU から利用出来ないようにしたいなと思っています。
Transit Gateway の各イベントログを確認
OU 配下を禁止させたいので、まぁ SCP を使うことになりそうです。
そして SCP を使うためにはどのアクションをどう制御するのか把握したいところです。
ということで先程やりたいことと同じようなOU/アカウント構成を用意して Transit Gateway の作成と共有、共有先アカウントからの利用を行ってみます。
そして CloudTrail ログなどを確認してみましょう。
Transit Gateway を作成後に共有する
Account1 で Transit Gateway を作成後に、他のアカウントへ共有を行います。
「Transit Gateway を共有する」という機能を使って共有を行うのですが、RAM で作成したリソース共有を指定する形です。よって Transit Gateway の共有範囲は RAM の設定次第という感じです。
RAM では共有リソースを作成し、その際にプリンシパルを指定します。
このプリンシパルが色々な指定方法があり、組織内に限らず指定することも可能です。組織内の場合でも AWS アカウント ID から組織 ID まで様々なスコープを指定することが出来ます。
今回は外部プリンシパルを許可しないかつ自分の組織 ID を指定しました。
この時、CreateResourceShare
が実行されていました。
関係しそうなパラメータのみ抜粋したイベントデータが次のものです。(プロパティを便宜上削除しています)
{
"eventVersion": "1.09",
"userIdentity": { ... },
"eventSource": "ram.amazonaws.com",
"eventName": "CreateResourceShare",
"awsRegion": "ap-northeast-1",
"requestParameters": {
"name": "hoge0122ram",
"resourceArns": [],
"principals": [],
"permissionArns": [],
"allowExternalPrincipals": false,
"tags": []
},
"responseElements": {
"resourceShare": {
"allowExternalPrincipals": false,
"creationTime": 1736637374.383,
"lastUpdatedTime": 1736637374.383,
"name": "hoge0122ram",
"owningAccountId": "xxxxxxxxxxx1",
"resourceShareArn": "arn:aws:ram:ap-northeast-1:xxxxxxxxxxx1:resource-share/8f1737ca-98ca-4786-849a-ed65d84b116d",
"status": "ACTIVE",
"tags": []
}
},
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true,
}
RAM でリソース共有が作成出来たら、Transit Gateway の共有機能で指定します。
この時は、AssociateResourceShare
が実行されていました。
{
"eventVersion": "1.09",
"userIdentity": { ... },
"eventSource": "ram.amazonaws.com",
"eventName": "AssociateResourceShare",
"awsRegion": "ap-northeast-1",
"requestParameters": {
"resourceShareArn": "arn:aws:ram:ap-northeast-1:xxxxxxxxxxx1:resource-share/8f1737ca-98ca-4786-849a-ed65d84b116d",
"resourceArns": [
"arn:aws:ec2:ap-northeast-1:xxxxxxxxxxx1:transit-gateway/tgw-022576db7e6c1f206"
]
},
"responseElements": {
"resourceShareAssociations": [
{
"associatedEntity": "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxx1:transit-gateway/tgw-022576db7e6c1f206",
"associationType": "RESOURCE",
"external": false,
"resourceShareArn": "arn:aws:ram:ap-northeast-1:xxxxxxxxxxx1:resource-share/8f1737ca-98ca-4786-849a-ed65d84b116d",
"status": "ASSOCIATING"
}
]
},
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true
}
この時点で、組織内のどのアカウントからも Transit Gateway コンソールから共有された Transit Gateway の情報を参照出来るようになります。利用を禁止したい OU 配下のアカウントからは次のように確認が出来ます。なるほど。
共有された側でアタッチメントを作成する
ではこの Account5 から利用してみます。
まずは VPC アタッチメントを作成してみます。ここは共有側のアカウントでは作成できず、関連付けする VPC を所有しているアカウントが作成する必要があります。
この時、CreateTransitGatewayVpcAttachment
が実行されます。
{
"eventVersion": "1.10",
"userIdentity": { ... },
"eventSource": "ec2.amazonaws.com",
"eventName": "CreateTransitGatewayVpcAttachment",
"awsRegion": "ap-northeast-1",
"requestParameters": {
"CreateTransitGatewayVpcAttachmentRequest": {
"Options": {
"Ipv6Support": "disable",
"ApplianceModeSupport": "disable",
"SecurityGroupReferencingSupport": "enable",
"DnsSupport": "enable"
},
"TransitGatewayId": "tgw-022576db7e6c1f206",
"VpcId": "vpc-0258c46d8ab83eab6",
"TagSpecifications": {
"ResourceType": "transit-gateway-attachment",
"tag": 1,
"Tag": {
"Value": "hoge0112attachment",
"tag": 1,
"Key": "Name"
}
},
"SubnetIds": {
"tag": 1,
"content": "subnet-017f98ea9b740e73b"
}
}
},
"responseElements": {
"CreateTransitGatewayVpcAttachmentResponse": {
"xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/",
"transitGatewayVpcAttachment": {
"tagSet": {
"item": {
"value": "hoge0112attachment",
"key": "Name"
}
},
"creationTime": "2025-01-11T23:23:24.000Z",
"transitGatewayAttachmentId": "tgw-attach-01331730939385c4f",
"transitGatewayId": "tgw-022576db7e6c1f206",
"vpcId": "vpc-0258c46d8ab83eab6",
"options": {
"applianceModeSupport": "disable",
"securityGroupReferencingSupport": "enable",
"dnsSupport": "enable",
"ipv6Support": "disable"
},
"state": "pendingAcceptance",
"vpcOwnerId": "xxxxxxxxxxx5",
"subnetIds": {
"item": "subnet-017f98ea9b740e73b"
}
},
"requestId": "960dca5b-8c97-4c9b-972b-2c09eef78fc3"
}
},
"readOnly": false,
"eventType": "AwsApiCall",
"managementEvent": true
}
この作成しただけだとまだアタッチメントは使うことが出来ません。ステータスがPending Acceptance
となっています。
ということで、Transit Gateway の所有者に承認してもらう必要があります。
このとき、AcceptTransitGatewayVpcAttachment
が実行されます。
{
"eventVersion": "1.10",
"userIdentity": { ... },
"eventSource": "ec2.amazonaws.com",
"eventName": "AcceptTransitGatewayVpcAttachment",
"awsRegion": "ap-northeast-1",
"requestParameters": {
"AcceptTransitGatewayVpcAttachmentRequest": {
"TransitGatewayAttachmentId": "tgw-attach-01331730939385c4f"
}
},
"responseElements": {
"AcceptTransitGatewayVpcAttachmentResponse": {
"xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/",
"transitGatewayVpcAttachment": {
"transitGatewayAttachmentId": "tgw-attach-01331730939385c4f",
"transitGatewayId": "tgw-022576db7e6c1f206",
"vpcId": "vpc-0258c46d8ab83eab6",
"state": "pending",
"vpcOwnerId": "xxxxxxxxxxx5",
"subnetIds": {
"item": "subnet-017f98ea9b740e73b"
}
},
"requestId": "ced4f370-ab42-4408-a9a0-ecdb50ea2108"
}
}
}
ちなみに、Transit Gateway の「共有アタッチメントの自動承認」機能を有効化すると、この承認をスキップして自動承認させることが出来ます。
この時、CloudTrail イベントを観察する限りではAcceptTransitGatewayVpcAttachment
が発生せずに、CreateTransitGatewayVpcAttachment
直後ステータスがそのまま承認状態となります。
SCP で制限してみる
さて、アタッチメントが使えるようになるまでのイベントが整理出来たので SCP で制御してみます。
先ほどまでで以下の流れであることがわかりました。
- Transit Gateway を共有
- RAM を共有(スコープは自由自在): CreateResourceShare
- Transit Gateway 共有機能で RAM リソースを指定する: AssociateResourceShare
- Transit Gateway アタッチメントを作成
- 使いたい側からアタッチメントを作成する: CreateTransitGatewayVpcAttachment
- 管理側から承諾する(省略オプションあり): AcceptTransitGatewayVpcAttachment
今回は特定 Transit Gateway に対するアタッチメントの作成を禁止してみようかなと思います。
というのも、共有周りの制限も出来そうですが、複雑なポリシー実装になりそうな気がしているのと、既に共有済みの環境だと利用中の Transit Gateway に対する共有設定を変更する必要がありそうです。
また、アタッチメントの承諾部分を制御することも出来そうですが、ここも自動承諾機能があるので今回は一旦忘れます(対処しない)
また、厳密にはアタッチメント作成後にルートテーブルの関連付けなどもあるのですが、このあたりもデフォルトリソースの概念があるので今回はここも対応しません。
ということで、今回はCreateTransitGatewayVpcAttachment
アクションを禁止するポリシーを作成できれば良さそうです。
ただし、特定の Transit Gateway のみを制限するようにしたいと思います。Account1 から共有された以外の Transit Gateway については共有利用を許可したい場合があり得るからです。
これを行うためには IAM アクションごとの条件キーを確認する必要があります。
次のドキュメントのCreateTransitGatewayVpcAttachment
アクションの諸々を確認してみましょう。
指定出来る条件キーは以下のようです。
- subnet*
- aws:ResourceTag/${TagKey}
- ec2:AvailabilityZone
- ec2:ResourceTag/${TagKey}
- ec2:SubnetID
- ec2:Vpc
- vpc*
- aws:ResourceTag/${TagKey}
- ec2:ResourceTag/${TagKey}
- ec2:Tenancy
- ec2:VpcID
- transit-gateway*
- aws:ResourceTag/${TagKey}
- ec2:ResourceTag/${TagKey}
- ec2:transitGatewayId
ec2:transitGatewayId
が指定出来るのでこれで制限をかけれそうです。Transit Gateway の ID を指定出来そう。
あるいはタグを使った ABAC もありかもしれないですね。
次のように制限したい Transit Gateway ID を指定した SCP を作成して OU にアタッチします。
もう一度アタッチメントを作成しようとすると SCP がアタッチされた OU 配下のアカウントでは作成に失敗しました。一方で SCP がアタッチされていない OU では作成に成功します。
さらに、SCP がアタッチされた OU でも他の Transit Gateway へのアタッチメント作成は出来ました。良い感じです。
さいごに
本日は特定の被共有中 Transit Gateway への VPC アタッチメント作成を SCP で禁止してみました。
アタッチメント作成が出来ないので OU 配下で特定の Transit Gateway を使った通信は禁止出来る気がします。
一方で、Transit Gateway の情報参照もさせたくない場合(例えば組織内に Transit Gateway が存在することを認識させたくない場合)は RAM の共有部分を制御する必要がありそうです。このあたりも別途コントロール方法を調べてみようかなと思います。